﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using shop.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace shop.Bll
{
    /// <summary> 封装旺店通SDK </summary>
    public class WdtApi
    {

        NLog.ILogger _logger = NLog.LogManager.GetLogger("trade");

        JsonSerializerSettings settings = new JsonSerializerSettings();


//#if DEBUG

        //readonly string _sid = "apidevnew2";
        //readonly string _appkey = "wlf2-test";
        //readonly string _appsecret = "cc15cb058";

        //
        readonly string _sid = "wlf2";
        readonly string _appkey = "wlf2-ot";
        readonly string _appsecret = "44c70e80d5242541f1508928a29a61fc";

        ////奇门
        //readonly string _sid = "wlf2";
        //readonly string _appkey = "21363512";
        //readonly string _appsecret = "44c70e80d5242541f1508928a29a61fc";


        //readonly string _baseUrl = "https://sandbox.wangdian.cn/openapi2/";
        readonly string _baseUrl = "https://api.wangdian.cn/openapi2/";

//#else
//        //readonly string _sid = "wlf2";
//        //readonly string _appkey = "wlf2-ot";
//        //readonly string _appsecret = "44c70e80d5242541f1508928a29a61fc";

//        //readonly string _baseUrl = "https://api.wangdian.cn/openapi2/";
//#endif

        public WdtApi()
        {
            settings.Converters.Add(new MyIsoDateTimeConverter());
        }


        public WdtApi(string url): this()
        {
            _url = url;
        }


        #region 流式api调用


        private string _url;
        private Dictionary<string, string> _dict;


        public WdtApi UseUrl(string url)
        {
            _url = url;
            return this;
        }

        /// <summary>  </summary>
        public WdtApi AddParam(string name, string value)
        {
            if (this._dict == null)
            {
                _dict = new Dictionary<string, string>();
            }

            _dict.Add(name, value);

            return this;
        }

        /// <summary>  </summary>
        public WdtApi AddParamIf(bool ifValue, string name, string value)
        {
            if (!ifValue)
            {
                return this;
            }

            if (this._dict == null)
            {
                _dict = new Dictionary<string, string>();
            }

            _dict.Add(name, value);

            return this;
        }


        /// <summary>  </summary>
        public WdtApi AddParamIfNotEmpty(string name, string value)
        {
            return AddParamIf(!string.IsNullOrEmpty(value), name, value);
        }


        ///// <summary>  </summary>
        //public WdtApi UseParam(Dictionary<string, string> para)
        //{
        //    _dict = para;

        //    return this;
        //}


        public async Task<string> Post()
        {
            return await Query(_url, _dict);
        }


        public async Task<T> Post<T>()
            where T : class
        {

            var res = await Query(_url, _dict);

            if (string.IsNullOrEmpty(res))
            {
                return null;
            }

            //var data = JObject.Parse(res).ToObject<T>();

#if DEBUG
            _logger.Info(res);

#endif
            var result = JsonConvert.DeserializeObject<T>(res, settings);
            return result;
            
            //var data = JsonConvert.DeserializeObject<T>(res, )
            //return data;

        }


        #endregion




        /// <summary> 查询 </summary>
        private async Task<string> Query(string url, Dictionary<string, string> param)
        {
            if (string.IsNullOrEmpty(url))
            {
                return null;
            }

            if (!url.StartsWith("http"))
            {
                url = _baseUrl + (url.StartsWith("/") ? url : "/" + url);
            }


            // 
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            Stream serviceRequestBodyStream = null;

            if (param== null)
            {
                param = new Dictionary<string, string>();
            }

            try
            {
                request = (HttpWebRequest)WebRequest.Create(url);
                request.Credentials = CredentialCache.DefaultCredentials;
                request.KeepAlive = false;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";

                UTF8Encoding encoding = new UTF8Encoding();

                double epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

                param.Add("sid", _sid);
                param.Add("appkey", _appkey);
                param.Add("timestamp", epoch.ToString("f0"));

                string postData = CreateParam(param, true);
                byte[] bodyBytes = encoding.GetBytes(postData);
                request.ContentLength = bodyBytes.Length;
                using (serviceRequestBodyStream = await request.GetRequestStreamAsync())
                {
                    await serviceRequestBodyStream.WriteAsync(bodyBytes, 0, bodyBytes.Length);
                    serviceRequestBodyStream.Close();
                    serviceRequestBodyStream.Dispose();

                    using (response = (HttpWebResponse)await request.GetResponseAsync())
                    {
                        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                        {
                            string result = await reader.ReadToEndAsync();
                            reader.Close();

#if DEBUG
                            _logger.Debug("api: "+url+"\r\n"+result);
#endif
                            return result;
                        }
                    }
                }
            }
            catch (Exception)
            {
                //LogManager.WriteError(ex, "Post");
                throw;
            }
            finally
            {
                response?.Close();
                request?.Abort();
            }
        }



        private string CreateParam(Dictionary<string,string> param, bool isLower = false)
        {
            //排序
            param = param.OrderBy(r => r.Key).ToDictionary(r => r.Key, r => r.Value);

            StringBuilder sb = new StringBuilder();
            int i = 0;
            foreach (var item in param)
            {
                if (item.Key == "sign")
                    continue;
                if (i > 0)
                {
                    sb.Append(";");
                }
                i++;
                sb.Append(item.Key.Length.ToString("00"));
                sb.Append("-");
                sb.Append(item.Key);
                sb.Append(":");

                sb.Append(item.Value.Length.ToString("0000"));
                sb.Append("-");
                sb.Append(item.Value);
            }
            if (isLower)
                param.Add("sign", MD5Encrypt(sb + _appsecret).ToLower());
            else
            {
                param.Add("sign", MD5Encrypt(sb + _appsecret));
            }
            sb = new StringBuilder();
            i = 0;
            foreach (var item in param)
            {
                if (i == 0)
                    _ = sb.Append(string.Format("{0}={1}", item.Key, HttpUtility.UrlEncode(item.Value, Encoding.UTF8)));
                else
                    _ = sb.Append(string.Format("&{0}={1}", item.Key, HttpUtility.UrlEncode(item.Value, Encoding.UTF8)));
                i++;
            }

            
            return sb.ToString();
        }

        private string MD5Encrypt(string strText)
        {
            MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] result = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(strText));
            string strMd5 = BitConverter.ToString(result);
            strMd5 = strMd5.Replace("-", "");
            return strMd5;// System.Text.Encoding.Default.GetString(result);
        }







    }
}
